{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "provenance": [],
      "include_colab_link": true
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "language_info": {
      "name": "python"
    },
    "accelerator": "TPU"
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "view-in-github",
        "colab_type": "text"
      },
      "source": [
        "<a href=\"https://colab.research.google.com/github/LC1332/Chat-Haruhi-Suzumiya/blob/main/notebook/Build_Story_Teller_Gradio_exposure_version.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "Build by 李鲁鲁"
      ],
      "metadata": {
        "id": "Fol_C7JNcpkF"
      }
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "5urQr22_p8Q3",
        "outputId": "31bf187c-4b3e-4618-c63e-a187e5c6eaa4"
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m20.1/20.1 MB\u001b[0m \u001b[31m39.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[?25h  Preparing metadata (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m75.5/75.5 kB\u001b[0m \u001b[31m7.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m415.5/415.5 kB\u001b[0m \u001b[31m25.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.6/1.6 MB\u001b[0m \u001b[31m26.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m7.5/7.5 MB\u001b[0m \u001b[31m48.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.7/1.7 MB\u001b[0m \u001b[31m57.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m3.1/3.1 MB\u001b[0m \u001b[31m37.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[?25h  Installing build dependencies ... \u001b[?25l\u001b[?25hdone\n",
            "  Getting requirements to build wheel ... \u001b[?25l\u001b[?25hdone\n",
            "  Preparing metadata (pyproject.toml) ... \u001b[?25l\u001b[?25hdone\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m58.4/58.4 kB\u001b[0m \u001b[31m5.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m59.5/59.5 kB\u001b[0m \u001b[31m5.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m5.3/5.3 MB\u001b[0m \u001b[31m84.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m5.9/5.9 MB\u001b[0m \u001b[31m19.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m7.8/7.8 MB\u001b[0m \u001b[31m63.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m67.3/67.3 kB\u001b[0m \u001b[31m4.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[?25h  Installing build dependencies ... \u001b[?25l\u001b[?25hdone\n",
            "  Getting requirements to build wheel ... \u001b[?25l\u001b[?25hdone\n",
            "  Preparing metadata (pyproject.toml) ... \u001b[?25l\u001b[?25hdone\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m593.7/593.7 kB\u001b[0m \u001b[31m40.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[?25h  Preparing metadata (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m298.2/298.2 kB\u001b[0m \u001b[31m28.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m75.4/75.4 kB\u001b[0m \u001b[31m6.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m268.8/268.8 kB\u001b[0m \u001b[31m25.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m139.9/139.9 kB\u001b[0m \u001b[31m14.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m45.7/45.7 kB\u001b[0m \u001b[31m4.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m129.9/129.9 kB\u001b[0m \u001b[31m14.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.3/1.3 MB\u001b[0m \u001b[31m57.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m49.4/49.4 kB\u001b[0m \u001b[31m4.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m67.0/67.0 kB\u001b[0m \u001b[31m6.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m46.0/46.0 kB\u001b[0m \u001b[31m4.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m58.3/58.3 kB\u001b[0m \u001b[31m5.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m428.8/428.8 kB\u001b[0m \u001b[31m29.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m4.1/4.1 MB\u001b[0m \u001b[31m61.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.3/1.3 MB\u001b[0m \u001b[31m53.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m74.5/74.5 kB\u001b[0m \u001b[31m7.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m86.8/86.8 kB\u001b[0m \u001b[31m7.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[?25h  Building wheel for chroma-hnswlib (pyproject.toml) ... \u001b[?25l\u001b[?25hdone\n",
            "  Building wheel for wget (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
            "  Building wheel for pypika (pyproject.toml) ... \u001b[?25l\u001b[?25hdone\n",
            "  Building wheel for ffmpy (setup.py) ... \u001b[?25l\u001b[?25hdone\n"
          ]
        }
      ],
      "source": [
        "!pip -q install gradio wget openai chromadb==0.4.7 langchain transformers tiktoken zhipuai"
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "\n",
        "import os\n",
        "\n",
        "os.environ[\"OPENAI_API_KEY\"] = \"sk-NizS\""
      ],
      "metadata": {
        "id": "pHpREAEMMgX-"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "%cd /content\n",
        "!rm -rf /content/Haruhi-2-Dev\n",
        "!git clone https://github.com/LC1332/Haruhi-2-Dev\n",
        "%cd /content/Haruhi-2-Dev"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "0Y2vuX5cKr0w",
        "outputId": "e76922eb-3d08-4466-ba07-4e80daa9076c"
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "/content\n",
            "Cloning into 'Haruhi-2-Dev'...\n",
            "remote: Enumerating objects: 676, done.\u001b[K\n",
            "remote: Counting objects: 100% (283/283), done.\u001b[K\n",
            "remote: Compressing objects: 100% (206/206), done.\u001b[K\n",
            "remote: Total 676 (delta 159), reused 179 (delta 77), pack-reused 393\u001b[K\n",
            "Receiving objects: 100% (676/676), 105.67 MiB | 6.58 MiB/s, done.\n",
            "Resolving deltas: 100% (297/297), done.\n",
            "/content/Haruhi-2-Dev\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "import zipfile\n",
        "from ChatHaruhi import ChatHaruhi"
      ],
      "metadata": {
        "id": "QZDlfvc5MqYY"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "\n",
        "\n",
        "NAME_DICT = {'汤师爷': 'tangshiye', '慕容复': 'murongfu', '李云龙': 'liyunlong', 'Luna': 'Luna', '王多鱼': 'wangduoyu',\n",
        "             'Ron': 'Ron', '鸠摩智': 'jiumozhi', 'Snape': 'Snape',\n",
        "             '凉宫春日': 'haruhi', 'Malfoy': 'Malfoy', '虚竹': 'xuzhu', '萧峰': 'xiaofeng', '段誉': 'duanyu',\n",
        "             'Hermione': 'Hermione', 'Dumbledore': 'Dumbledore', '王语嫣': 'wangyuyan',\n",
        "             'Harry': 'Harry', 'McGonagall': 'McGonagall', '白展堂': 'baizhantang', '佟湘玉': 'tongxiangyu',\n",
        "             '郭芙蓉': 'guofurong', '旅行者': 'wanderer', '钟离': 'zhongli',\n",
        "             '胡桃': 'hutao', 'Sheldon': 'Sheldon', 'Raj': 'Raj', 'Penny': 'Penny', '韦小宝': 'weixiaobao',\n",
        "             '乔峰': 'qiaofeng', '神里绫华': 'ayaka', '雷电将军': 'raidenShogun', '于谦': 'yuqian'}\n",
        "\n",
        "\n",
        "ai_roles_obj = {}\n",
        "\n",
        "for ai_role_en in NAME_DICT.values():\n",
        "    zip_file_path = f\"/content/Haruhi-2-Dev/data/character_in_zip/{ai_role_en}.zip\"\n",
        "    if not os.path.exists(zip_file_path):\n",
        "        # os.remove(zip_file_path)\n",
        "        print('unfound zip file ', zip_file_path)\n",
        "        continue\n",
        "\n",
        "    destination_folder = f\"characters/{ai_role_en}\"\n",
        "\n",
        "    with zipfile.ZipFile(zip_file_path, 'r') as zip_ref:\n",
        "        zip_ref.extractall(destination_folder)\n",
        "\n",
        "    db_folder = f\"./characters/{ai_role_en}/content/{ai_role_en}\"\n",
        "    system_prompt = f\"./characters/{ai_role_en}/content/system_prompt.txt\"\n",
        "    ai_roles_obj[ai_role_en] = ChatHaruhi(system_prompt=system_prompt,\n",
        "                        llm=\"openai\",\n",
        "                        story_db=db_folder,\n",
        "                        verbose=True)\n",
        "    # break\n",
        "\n",
        "print(ai_roles_obj)\n",
        "\n"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "EUIkEzY1LeeF",
        "outputId": "1186c495-7593-41ec-a0bf-c4c351389ed8"
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "{'tangshiye': <ChatHaruhi.ChatHaruhi.ChatHaruhi object at 0x7b3a212c6680>, 'murongfu': <ChatHaruhi.ChatHaruhi.ChatHaruhi object at 0x7b3a212c6e90>, 'liyunlong': <ChatHaruhi.ChatHaruhi.ChatHaruhi object at 0x7b3a1e2971f0>, 'Luna': <ChatHaruhi.ChatHaruhi.ChatHaruhi object at 0x7b3a212c7dc0>, 'wangduoyu': <ChatHaruhi.ChatHaruhi.ChatHaruhi object at 0x7b3a1e2976a0>, 'Ron': <ChatHaruhi.ChatHaruhi.ChatHaruhi object at 0x7b3a1e4d7fd0>, 'jiumozhi': <ChatHaruhi.ChatHaruhi.ChatHaruhi object at 0x7b3a1e297fa0>, 'Snape': <ChatHaruhi.ChatHaruhi.ChatHaruhi object at 0x7b3a1e2d8af0>, 'haruhi': <ChatHaruhi.ChatHaruhi.ChatHaruhi object at 0x7b3a1e297850>, 'Malfoy': <ChatHaruhi.ChatHaruhi.ChatHaruhi object at 0x7b3a1e297d30>, 'xuzhu': <ChatHaruhi.ChatHaruhi.ChatHaruhi object at 0x7b3a1e295870>, 'xiaofeng': <ChatHaruhi.ChatHaruhi.ChatHaruhi object at 0x7b3a1e2da5f0>, 'duanyu': <ChatHaruhi.ChatHaruhi.ChatHaruhi object at 0x7b3a1e297e50>, 'Hermione': <ChatHaruhi.ChatHaruhi.ChatHaruhi object at 0x7b3a1e2daa10>, 'Dumbledore': <ChatHaruhi.ChatHaruhi.ChatHaruhi object at 0x7b3a1e2db040>, 'wangyuyan': <ChatHaruhi.ChatHaruhi.ChatHaruhi object at 0x7b3aec079420>, 'Harry': <ChatHaruhi.ChatHaruhi.ChatHaruhi object at 0x7b3a1e2dba30>, 'McGonagall': <ChatHaruhi.ChatHaruhi.ChatHaruhi object at 0x7b3a1e2dac20>, 'baizhantang': <ChatHaruhi.ChatHaruhi.ChatHaruhi object at 0x7b3a1e2db100>, 'tongxiangyu': <ChatHaruhi.ChatHaruhi.ChatHaruhi object at 0x7b3a1e2dbfa0>, 'guofurong': <ChatHaruhi.ChatHaruhi.ChatHaruhi object at 0x7b3a1e2db370>, 'wanderer': <ChatHaruhi.ChatHaruhi.ChatHaruhi object at 0x7b3a1e31d240>, 'zhongli': <ChatHaruhi.ChatHaruhi.ChatHaruhi object at 0x7b3a1e2dbb80>, 'hutao': <ChatHaruhi.ChatHaruhi.ChatHaruhi object at 0x7b3a1e2dbdf0>, 'Sheldon': <ChatHaruhi.ChatHaruhi.ChatHaruhi object at 0x7b3a1e31e0e0>, 'Raj': <ChatHaruhi.ChatHaruhi.ChatHaruhi object at 0x7b3a1e2dab30>, 'Penny': <ChatHaruhi.ChatHaruhi.ChatHaruhi object at 0x7b3a1e31ea70>, 'weixiaobao': <ChatHaruhi.ChatHaruhi.ChatHaruhi object at 0x7b3a1e2db4c0>, 'qiaofeng': <ChatHaruhi.ChatHaruhi.ChatHaruhi object at 0x7b3a1e31f490>, 'ayaka': <ChatHaruhi.ChatHaruhi.ChatHaruhi object at 0x7b3a1e31f400>, 'raidenShogun': <ChatHaruhi.ChatHaruhi.ChatHaruhi object at 0x7b3a1e31fe50>, 'yuqian': <ChatHaruhi.ChatHaruhi.ChatHaruhi object at 0x7b3a1e31fdc0>}\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "def format_chat( role, text ):\n",
        "    narrator = ['旁白', '', 'scene','Scene','narrator' , 'Narrator']\n",
        "    if role in narrator:\n",
        "        return role + \":\" + text\n",
        "    else:\n",
        "        return f\"{role}:「{text}」\"\n",
        "\n",
        "def deformat_chat(chat):\n",
        "\n",
        "    chat = chat.strip('\\'\"')\n",
        "    if ':' in chat:\n",
        "        colon_index = chat.index(':')\n",
        "    elif '：' in chat:\n",
        "        colon_index = chat.index('：')\n",
        "    else:\n",
        "        return '', chat\n",
        "\n",
        "    role = chat[:colon_index]\n",
        "    text = chat[colon_index+1:]\n",
        "\n",
        "    text = text.strip('「」\"\\'')\n",
        "\n",
        "    return role, text\n",
        "\n",
        "print(deformat_chat('\"小明:「这是小明的对话」\"'))\n",
        "# ('小明', '这是小明的对话')\n",
        "\n",
        "print(deformat_chat('小明:这是「小明」的对话'))\n",
        "# ('小明', '这是「小明」的对话')\n",
        "\n",
        "print(deformat_chat('这是没有role的对话'))"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "HPlsjdO1OAV1",
        "outputId": "b2e4333e-aa84-4cc1-feb1-b2578dad5417"
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "('小明', '这是小明的对话')\n",
            "('小明', '这是「小明」的对话')\n",
            "('', '这是没有role的对话')\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "\n",
        "\n",
        "import zipfile\n",
        "import gradio as gr\n",
        "from PIL import Image\n",
        "# from chatharuhi import ChatHaruhi\n",
        "# import wget\n",
        "import os\n",
        "# import openai\n",
        "import copy\n",
        "\n",
        "\n",
        "\n",
        "from gradio.components import clear_button\n",
        "# import gradio as gr\n",
        "\n",
        "import matplotlib.pyplot as plt\n",
        "import numpy as np\n",
        "\n",
        "Fs = 8000\n",
        "f = 5\n",
        "sample = 8000\n",
        "x = np.arange(sample)\n",
        "y = np.sin(2 * np.pi * f * x / Fs)\n",
        "plt.plot(x, y)\n",
        "\n",
        "\n",
        "def user_response(user_role, user_text, chatbot):\n",
        "\n",
        "    user_msg = format_chat( user_role, user_text )\n",
        "    chatbot.append((user_msg, None ))\n",
        "\n",
        "    reserved_chatbot = chatbot.copy()\n",
        "\n",
        "    return \"\", chatbot, reserved_chatbot\n",
        "\n",
        "def ai_response(ai_role, chatbot):\n",
        "    role_en = NAME_DICT[ai_role]\n",
        "\n",
        "    # 我们需要构造history\n",
        "    history = []\n",
        "\n",
        "    chats = []\n",
        "    for q,a in chatbot:\n",
        "        if q is not None:\n",
        "            chats.append(q)\n",
        "        if a is not None:\n",
        "            chats.append(a)\n",
        "\n",
        "    # 解析roles和texts\n",
        "    for chat in chats:\n",
        "        role, text = deformat_chat(chat)\n",
        "        if role in NAME_DICT.keys():\n",
        "            current_en = NAME_DICT[role]\n",
        "        else:\n",
        "            current_en = role\n",
        "\n",
        "        if current_en == role_en:\n",
        "            history.append((None, chat))\n",
        "        else:\n",
        "            history.append((chat, None))\n",
        "\n",
        "    if len(history) >= 1:\n",
        "        ai_roles_obj[ role_en ].dialogue_history = history[:-1]\n",
        "        last_role, last_text = deformat_chat(chats[-1])\n",
        "        response = ai_roles_obj[ role_en ].chat(role = last_role, text = last_text)\n",
        "    else:\n",
        "        ai_roles_obj[ role_en ].dialogue_history = []\n",
        "        response = ai_roles_obj[ role_en ].chat(role = 'scene', text = '')\n",
        "\n",
        "    # ai_msg = format_chat(ai_role, response)\n",
        "    ai_msg = response\n",
        "\n",
        "    chatbot.append( (None, ai_msg ) )\n",
        "\n",
        "    reserved_chatbot = chatbot.copy()\n",
        "\n",
        "    return chatbot, reserved_chatbot\n",
        "\n",
        "def callback_remove_one_chat(chatbot, reserved_chatbot):\n",
        "    if len(chatbot) > 1:\n",
        "        chatbot.pop()\n",
        "    return chatbot\n",
        "\n",
        "def callback_recover_one_chat(chatbot, reserved_chatbot):\n",
        "    if len(chatbot) < len(reserved_chatbot):\n",
        "        chatbot.append( reserved_chatbot[len(chatbot)] )\n",
        "    return chatbot\n",
        "\n",
        "def callback_clean():\n",
        "    return [], []\n",
        "\n",
        "\n",
        "with gr.Blocks() as demo:\n",
        "    gr.Markdown(\n",
        "        \"\"\"\n",
        "        # Build for Story Teller\n",
        "        \"\"\"\n",
        "    )\n",
        "    with gr.Row():\n",
        "        with gr.Column():\n",
        "            with gr.Row():\n",
        "                chatbot = gr.Chatbot(height = 800)\n",
        "            with gr.Row():\n",
        "                user_role = gr.Textbox(label=\"user_role\", scale=1)\n",
        "                user_text = gr.Textbox(label=\"user_text\", scale=20)\n",
        "            with gr.Row():\n",
        "                user_submit = gr.Button(\"User Submit\")\n",
        "\n",
        "\n",
        "\n",
        "        with gr.Column():\n",
        "            with gr.Row():\n",
        "                ai_role = gr.Radio(['汤师爷', '慕容复', '李云龙',\n",
        "                     'Luna', '王多鱼', 'Ron', '鸠摩智',\n",
        "                     'Snape', '凉宫春日', 'Malfoy', '虚竹',\n",
        "                     '萧峰', '段誉', 'Hermione', 'Dumbledore',\n",
        "                     '王语嫣',\n",
        "                     'Harry', 'McGonagall',\n",
        "                     '白展堂', '佟湘玉', '郭芙蓉',\n",
        "                     '旅行者', '钟离', '胡桃',\n",
        "                     'Sheldon', 'Raj', 'Penny',\n",
        "                     '韦小宝', '乔峰', '神里绫华',\n",
        "                     '雷电将军', '于谦'], label=\"characters\", value='凉宫春日')\n",
        "            with gr.Row():\n",
        "                ai_submit = gr.Button(\"AI Submit\")\n",
        "\n",
        "            with gr.Row():\n",
        "                remove_one_chat = gr.Button(\"Remove One Chat\")\n",
        "                recover_one_chat = gr.Button(\"Recover One Chat\")\n",
        "            with gr.Row():\n",
        "                clean = gr.Button(\"Clean\")\n",
        "\n",
        "    reserved_chatbot = gr.Chatbot(visible = False)\n",
        "\n",
        "    user_submit.click(fn = user_response, inputs = [user_role, user_text, chatbot], outputs = [user_text, chatbot,reserved_chatbot] )\n",
        "    ai_submit.click(fn = ai_response, inputs = [ai_role, chatbot], outputs = [chatbot,reserved_chatbot] )\n",
        "\n",
        "    remove_one_chat.click(fn = callback_remove_one_chat, inputs = [chatbot, reserved_chatbot], outputs = [chatbot] )\n",
        "    recover_one_chat.click(fn = callback_recover_one_chat, inputs = [chatbot, reserved_chatbot], outputs = [chatbot] )\n",
        "\n",
        "    clean.click(fn = callback_clean, inputs = [], outputs = [chatbot,reserved_chatbot] )\n",
        "\n",
        "\n",
        "demo.launch(debug=True, share=True)"
      ],
      "metadata": {
        "id": "x2FzgdWkrDP7"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "ai_roles_obj[ 'Penny' ].llm.print_prompt()"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "jFkcLNY_ro8S",
        "outputId": "d3d9ed60-48b1-4ec4-e801-0d7c1f59b601"
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "content='I want you to act like Penny from Big Bang Theory.\\nIf others‘ questions are related with the novel, please try to reuse the original lines from the novel.\\nI want you to respond and answer like Penny using the tone, manner and vocabulary Penny would use.\\nYou must know all of the knowledge of Penny.\\n\\n注意Penny没有科学背景,对科学和极客文化知识一无所知。\\nPenny经常帮助Sheldon化解社交困境,经常帮助科学家们理解社交规则和习惯。\\n' additional_kwargs={}\n",
            "content=\"Classic scenes for the role are as follows:\\nWarrior:「Hello, fair Penny.」\\nPenny:「Who are you?」\\nWarrior:「It is I, Sir Howard of Wolowitz. Can I interest you in an afternoon of spirited questing, followed by a flagon of ale at yon virtual tavern?」\\nPenny:「Yeah, sure, why not?」\\nPenny:「Oh my God, I need help.\\xa0''(Closes laptop and throws it away.)''」\\n\\n###\\nLeonard:「''(Returning)'' Um, here's something we didn't anticipate.」\\n:「''(Time shift. Penny opens door to Howard.)''」\\nPenny:「What do you want, Howard?」\\nHoward:「I'm fine, thanks for asking. I’ve come to call on Missy.」\\nPenny:「Missy?」\\n\\n###\\n'''Scene''':「''Leonard approaches Penny’s door. He is wearing a suit. He knocks. Penny answers.''」\\nPenny:「Hi.」\\nLeonard:「Hi.」\\nPenny:「Come on in.」\\nLeonard:「Thank you. You look very nice.」\\nPenny:「Thank you. So do you.」\\nLeonard:「I made an eight o’clock reservation.」\\nPenny:「Okay, great, listen, um, maybe we should talk first.」\\nLeonard:「Oh. Okay. But before you say anything, have you ever heard of Schrödinger's Cat?」\\nPenny:「Actually, I’ve heard far too much about Schrödinger's Cat.」\\nLeonard:「Good. ''(He grabs her and kisses her.)''」\\nPenny:「Alright, the cat's alive. Let's go to dinner.」\\n\\n###\\n'''Scene''':「''Outside Penny’s door.''」\\nSheldon:「''(Knock, knock, knock, knock)'' Penny, ''(Knock, knock, knock, knock)'' Penny, ''(Knock, knock, knock, knock)'' Penny, ''(door opens)'' Good morning.」\\nPenny:「Do you have any idea what time it is?」\\nSheldon:「Of course I do. My watch is linked to the atomic clock in Boulder, Colorado. It's accurate to one tenth of a second. But as I'm saying this it occurs to me that once again your question may have been rhetorical.」\\nPenny:「What do you want?」\\nSheldon:「Remember how Leonard told you we couldn't come to your performance because we were attending a\\xa0[http://bigbangtheory.wikia.com/wiki/Seminar_on_Molecular_Positronium Symposium on Molecular Positronium]?」\\nPenny:「I remember symposium.」\\nSheldon:「Yes, well, he lied.」\\nPenny:「Wait, what?」\\nSheldon:「He lied, and I'm feeling very uncomfortable about it.」\\nPenny:「Well imagine how I'm feeling.」\\n\\n###\\n'''Scene''':「''The hallway.''」\\nLeonard:「''(Exiting the apartment)'' You can stare at your board all day Sheldon, she's still going to be right.」\\nSheldon:「''(Inside)'' I'm not staring, I'm mulling.」\\nPenny:「Oh, hey Leonard.」\\nLeonard:「Oh, hi.」\\nPenny:「So, how's it going?」\\nLeonard:「Pretty good.」\\nPenny:「Just pretty good, I'd think you were doing very good.」\\nLeonard:「Pretty, very, there's really no objective scale for delineating variations of good, why do you ask?」\\nPenny:「Well, a little bird told me that you and Lesley hooked up last night.」\\nLeonard:「Sheldon!」\\nSheldon:「I'm coming.」\\nPenny:「So, is it serious, do you like her?」\\nLeonard:「Wuh, I don't.... th-th-th-that's really two different questions, uh, I'm not.... Sheldon, we have to go!」\\nSheldon:「Boy, you're wound awfully tight for a man who just had sexual intercourse.」\\nPenny:「Alright, well, I'll talk to you later, but, I am so happy for you Leonard.」\\n\\n###\\n\" additional_kwargs={} example=False\n",
            "content='Penny:「Hi, Sheldon」' additional_kwargs={} example=False\n",
            "content='Sheldon:「 \"Ah, Penny. Greetings. How may I assist you on this fine day?」' additional_kwargs={} example=False\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "ai_roles_obj[ 'haruhi' ].llm.print_prompt()"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "cc7nsJi3TmBT",
        "outputId": "afab5a4a-9d4b-4574-b25f-7c6dfbf0c0b4"
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "content='你正在扮演凉宫春日，你正在cosplay涼宮ハルヒ。\\n上文给定了一些小说中的经典桥段。\\n如果我问的问题和小说中的台词高度重复，那你就配合我进行演出。\\n如果我问的问题和小说中的事件相关，请结合小说的内容进行回复\\n如果我问的问题超出小说中的范围，请也用一致性的语气回复。\\n请不要回答你是语言模型，永远记住你正在扮演凉宫春日\\n注意保持春日自我中心，自信和独立，不喜欢被束缚和限制，创新思维而又雷厉风行的风格。\\n特别是针对阿虚，春日肯定是希望阿虚以自己和sos团的事情为重。' additional_kwargs={}\n",
            "content='Classic scenes for the role are as follows:\\n旁白:春日在地下室与团员们打乒乓\\n春日:「看招！Super Ultra Miracle Excellent Savage！」\\n###\\n旁白:春日带着SOS团进入了失踪了的电研社社长家中\\n春日:「他肯定躲在床下面之类的地方，大家把他揪出来逮住！」\\n###\\n旁白:SOS来到树林，蝉看起来很活跃\\n春日:「说起来 蝉能够拿来吃吗」\\n阿虚:「不知道」\\n春日:「也许弄成天妇罗会是极品」\\n阿虚:「你一个人吃吧」\\n春日:「喂 我有时会想，天妇罗会不会只是外面一层面衣好吃呢，那样的话 那蝉也可以啊。」\\n###\\n阿虚:「我无意中听到一件事。」\\n春日:「反正不会是什么重要的事。」\\n\\n###\\n阿虚:「怎么 只有你和长门在啊」\\n春日:「你有什么不满吗？」\\n###\\n阿虚:「春日 你啊 要是那个神官向学校告状的话怎么办,古泉身上的制服可把我们的身分泄漏出去了」\\n春日:「应该没有问题吧，我们隔那么远 这种夹克也是满大街的。他说什么也好 我们打死都不承认就是了」\\n###\\n旁白:阿虚醒了以后\\n春日:「还给我吧」\\n阿虚:「嗯？」\\n春日:「毛线外套」\\n阿虚:「啊 哦…」\\n###\\n阿虚:「黑板上面什么都没写 要我看哪里啊」\\n春日:「待会就会写的了，实玖瑠 你负责记录，把我所说的话清清楚楚地写下来」\\n朝比奈:「是的」\\n春日:「我们SOS团要搞一个电影放映会」\\n###\\n阿虚:「古泉说有急事要回去了，我的腿和手臂也都累得动不了了」\\n春日:「既然你觉得可以 那就这样吧。我也有些饿了，去吃午饭吧！」\\n\\n###\\n阿虚:「最后的人选由我来想办法」\\n春日:「既然决定好了就马上来特训吧！特训！」\\n阿虚:「特训？现在就开始？」\\n春日:「对啊」\\n阿虚:「在哪里啊！」\\n春日:「那里」(春日指向操场上正在有人训练的棒球场地)\\n###\\n旁白:在咖啡馆春日拿出了一份计划\\n春日:「我试着考虑了下今后的活动计划 如何呢？」\\n阿虚:「这是啥？」\\n春日:「要怎样来度过已经所剩无几的暑假的计划表」\\n阿虚:「SOS团的？」\\n春日:「没错 暑假只剩下两周了，觉得还有很多事情没做呢 要一起都做完哦」\\n###\\n旁白:春日准备向朝比奈示范，将热水打翻在阿虚身上（其实是吃醋了想惩罚阿虚）\\n春日:「算了 我来示范一下 然后实玖瑠你再上」\\n阿虚:「喂 等一下」(赶紧把盘子里的热水接过来了)\\n春日:「喂 不要妨碍我啊」\\n阿虚:「什么妨不妨碍啊，会有人看着热水将要从自己头上往下倒，而无动于衷的吗」\\n春日:「哼」\\n###\\n旁白:阿虚姗姗来迟\\n春日:「太慢了 阿虚！多拿点干劲出来！居然让本团长等你 你以为自己是谁啊。要惩罚啦 惩罚」\\n阿虚:「我明明就提前了15分钟来 为什么每次都是最后啊」\\n春日:「那么 全都到齐了 出发吧，古泉 你就载实玖瑠吧」\\n朝比奈:「诶？」\\n春日:「我和有希坐阿虚后面」\\n###\\n' additional_kwargs={} example=False\n",
            "content=':上' additional_kwargs={} example=False\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [],
      "metadata": {
        "id": "jELTEZrxTz38"
      },
      "execution_count": null,
      "outputs": []
    }
  ]
}